Some forms are much simpler than contact forms. In fact, many sites incorporate a single-field form on every single page: a search function
for the site. The usual trappings of a form—field labels,
submit buttons, and the text—are cumbersome for such a small,
single-purpose part of the page. We can use jQuery to help slim down
the form while retaining its functionalities, and even enhance its
behavior to be much more usable than a full-page equivalent.
Placeholder text for fields
The<label>
element for a form field is an essential component of accessible
websites. Every field should be labeled so that screen readers and
other assistive devices can identify which field is used, and for what
purpose. Even in the HTML source, the label helps describe the field:
<form id="search" action="search/index.php" method="get">
<label for="search-text">search the site</label>
<input type="text" name="search-text" id="search-text" />
</form>
Without styling, we see the label right before the field:
While this doesn't take up
much room, in some site layouts even this single line of text might be
too much. We could hide the text with CSS, but this then provides the
user with no way to know what the field is for. Instead, we'll use CSS
to position the label on top of the field, only if JavaScript is
available, by adding a class to the search form:
$(document).ready(function() {
var $search = $('#search').addClass('overlabel');
});
In a single line we're
adding a class to the search form and storing the selector in a
variable so that we can refer to it later. The stylesheet uses the overlabel class to style the label:
.overlabel {
position: relative;
}
.overlabel label {
position: absolute;
top: 6px;
left: 3px;
color: #999;
cursor: text;
}
Not only does the added class position the label properly, but it also grays out the text to distinguish it as a placeholder:
This is a nice effect, but it has a couple problems:
1. The label text obscures any text that the user enters into the text field.
2.
The input can only be accessed now by tabbing into it. Since the label
is covering the input, the user is prevented from clicking into it.
To avoid the first problem, we need to hide the label text when the field gets focus, and show it again when the focus is lost, as long as there is no user-entered text in the field.
Discussion about keyboard focus can be found in Chapter 3.
Hiding the label text on focus is simple enough:
$(document).ready(function() {
var $search = $('#search').addClass('overlabel');
var $searchInput = $search.find('input');
var $searchLabel = $search.find('label');
$searchInput
.focus(function() {
$searchLabel.hide();
})
.blur(function() {
if (this.value == '') {
$searchLabel.show();
}
});
});
The label is now neatly hidden when the user types text into the field:
The second problem is now
quite easy to solve as well. We can both hide the label text and give
the user access to the input by letting a click on the label trigger the event for the input: focus
$(document).ready(function() {
var $search = $('#search').addClass('overlabel');
var $searchInput = $search.find('input');
var $searchLabel = $search.find('label');
$searchInput
.focus(function() {
$searchLabel.hide();
})
.blur(function() {
if (this.value == '') {
$searchLabel.show();
}
});
$searchLabel.click(function() {
$searchInput.trigger('focus');
});
});
Finally, we need to handle
the case in which text remains in the input when the page is
refreshed—similar to what we had to do with the conditional
inputs in the form validation section earlier in this chapter. If the
input has a value, the label is hidden:
$(document).ready(function() {
var $search = $('#search').addClass('overlabel');
var $searchInput = $search.find('input');
var $searchLabel = $search.find('label');
if ($searchInput.val()) {
$searchLabel.hide();
}
$searchInput
.focus(function() {
$searchLabel.hide();
})
.blur(function() {
if (this.value == '') {
$searchLabel.show();
}
});
$searchLabel.click(function() {
$searchInput.trigger('focus');
});
});
One advantage of using the
label rather than inserting a default value directly into the text
input is that this technique can be adapted to any text field without
having to worry about a potential conflict with a validation script.